﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Collections;
using System.Diagnostics;

namespace Ellanet
{
    class vmrunInfoXmlWrapper
    {
        private XmlDocument vmrunInfoXmlDoc;

        public enum LocalFlag
        {
            True,
            False,
            Optional,
            Unknown
        }

        public enum CommandParameterType
        {
            text,
            boolean,
            list
        }

        public struct CommandParameter
        {
            public string name;
            public CommandParameterType type;
            public ArrayList items;
            public string hint;
        }

        public vmrunInfoXmlWrapper()
        {
            vmrunInfoXmlDoc = new XmlDocument();
            vmrunInfoXmlDoc.LoadXml(global::Ellanet.Properties.Resources.vmrunInfo_Xml);
        }

        public ArrayList GetHostFriendlyNames()
        {
            ArrayList names = new ArrayList();

            foreach (XmlNode hostNode in vmrunInfoXmlDoc.SelectNodes("vmrun/supported_hosts/host"))
            {
                names.Add(hostNode.SelectSingleNode("friendly_name").InnerText);
            }

            return names;
        }

        public LocalFlag GetLocalFlag(string hostFriendlyName)
        {
            if (vmrunInfoXmlDoc.SelectNodes(String.Format("vmrun/supported_hosts/host[friendly_name=\"{0}\"]", hostFriendlyName)).Count > 0)
            {
                switch (vmrunInfoXmlDoc.SelectSingleNode(String.Format("vmrun/supported_hosts/host[friendly_name=\"{0}\"]/local", hostFriendlyName)).InnerText)
                {
                    case "true":
                        return LocalFlag.True;
                    case "false":
                        return LocalFlag.False;
                    case "optional":
                        return LocalFlag.Optional;
                    default:
                        return LocalFlag.Unknown;
                }
            }
            else
            {
                return LocalFlag.Unknown;
            }
        }

        public string GetDefaultPort(string hostFriendlyName)
        {
            if (vmrunInfoXmlDoc.SelectNodes(String.Format("vmrun/supported_hosts/host[friendly_name=\"{0}\" and default_port]", hostFriendlyName)).Count > 0)
            {
                return vmrunInfoXmlDoc.SelectSingleNode(String.Format("vmrun/supported_hosts/host[friendly_name=\"{0}\"]/default_port", hostFriendlyName)).InnerText;
            }
            else
            {
                return null;
            }
        }

        public string GetConnectArgument(string hostFriendlyName)
        {
            if (vmrunInfoXmlDoc.SelectNodes(String.Format("vmrun/supported_hosts/host[friendly_name=\"{0}\" and connect_argument]", hostFriendlyName)).Count > 0)
            {
                return vmrunInfoXmlDoc.SelectSingleNode(String.Format("vmrun/supported_hosts/host[friendly_name=\"{0}\"]/connect_argument", hostFriendlyName)).InnerText;
            }
            else
            {
                return null;
            }
        }

        public string ConvertFriendlyNameToType(string hostFriendlyName)
        {
            if (vmrunInfoXmlDoc.SelectNodes(String.Format("vmrun/supported_hosts/host[friendly_name=\"{0}\"]", hostFriendlyName)).Count > 0)
            {
                return vmrunInfoXmlDoc.SelectSingleNode(String.Format("vmrun/supported_hosts/host[friendly_name=\"{0}\"]/name", hostFriendlyName)).InnerText;
            }
            else
            {
                return null;
            }
        }

        public string ConvertTypeToFriendlyName(string hostType)
        {
            if (vmrunInfoXmlDoc.SelectNodes(String.Format("vmrun/supported_hosts/host[name=\"{0}\"]", hostType)).Count > 0)
            {
                return vmrunInfoXmlDoc.SelectSingleNode(String.Format("vmrun/supported_hosts/host[name=\"{0}\"]/friendly_name", hostType)).InnerText;
            }
            else
            {
                return null;
            }
        }

        public ArrayList GetvmrunCommands(string category, ArrayList hostTypes)
        {
            ArrayList commands = new ArrayList();

            foreach (XmlNode commandNode in vmrunInfoXmlDoc.SelectNodes(String.Format("vmrun/commands/category[@name=\"{0}\"]/command/supported_hosts[{1}]", category, BuildSupportedHostXPath(hostTypes))))
            {
                commands.Add(commandNode.ParentNode.SelectSingleNode("name").InnerText);
            }

            return commands;
        }

        public ArrayList GetvmrunCommandCategories(ArrayList hostTypes)
        {
            ArrayList categories = new ArrayList();

            foreach (XmlNode commandNode in vmrunInfoXmlDoc.SelectNodes(String.Format("vmrun/commands/category/command/supported_hosts[{0}]", BuildSupportedHostXPath(hostTypes))))
            {
                if (!categories.Contains(commandNode.ParentNode.ParentNode.Attributes.GetNamedItem("name").Value))
                {
                    categories.Add(commandNode.ParentNode.ParentNode.Attributes.GetNamedItem("name").Value);
                }
            }

            return categories;
        }

        private string BuildSupportedHostXPath(ArrayList hostTypes)
        {
            string xpath = null;

            foreach (string host in hostTypes)
            {
                xpath += String.Format("host=\"{0}\" and ", host);
            }

            return xpath.Substring(0, (xpath.Length - 5));
        }

        public string GetCommandHint(string command)
        {
            return vmrunInfoXmlDoc.SelectSingleNode(String.Format("vmrun/commands/category/command[name=\"{0}\"]/hint", command)).InnerText;
        }

        public string GetParameterHint(string command, string parameter)
        {
            return vmrunInfoXmlDoc.SelectSingleNode(String.Format("vmrun/commands/category/command[name=\"{0}\"]/parameters/parameter[name=\"{1}\"]/hint", command, parameter)).InnerText;
        }

        public bool CommandHasParameters(string command)
        {
            return Convert.ToBoolean(vmrunInfoXmlDoc.SelectNodes(String.Format("vmrun/commands/category/command[name=\"{0}\"]/parameters/parameter", command)).Count > 0);
        }

        public CommandParameter[] GetCommandParameters(string command)
        {
            ArrayList parameters = new ArrayList();

            if (CommandHasParameters(command))
            {
                foreach (XmlNode parameterNode in vmrunInfoXmlDoc.SelectNodes(String.Format("vmrun/commands/category/command[name=\"{0}\"]/parameters/parameter", command)))
                {
                    CommandParameter parameter = new CommandParameter();
                    parameter.name = parameterNode.SelectSingleNode("name").InnerText;
                    parameter.hint = parameterNode.SelectSingleNode("hint").InnerText;

                    switch (parameterNode.Attributes.GetNamedItem("type").Value.ToLower())
                    {
                        case "text":
                            parameter.type = CommandParameterType.text;
                            break;
                        case "boolean":
                            parameter.type = CommandParameterType.boolean;
                            break;
                        case "list":
                            parameter.type = CommandParameterType.list;
                            ArrayList items = new ArrayList();

                            foreach (XmlNode itemNode in parameterNode.SelectNodes("items/item"))
                            {
                                items.Add(itemNode.InnerText);
                            }

                            parameter.items = items;
                            break;
                    }

                    parameters.Add(parameter);
                }
            }

            return (CommandParameter[])parameters.ToArray(typeof(CommandParameter));
        }

        public bool CommandRequiresVMXPath(string command)
        {
            return Convert.ToBoolean(vmrunInfoXmlDoc.SelectSingleNode(String.Format("vmrun/commands/category/command[name=\"{0}\"]/parameters", command)).Attributes.GetNamedItem("vmx_required").Value);
        }

        public bool CommandRequiresGuestLogin(string command)
        {
            return Convert.ToBoolean(vmrunInfoXmlDoc.SelectSingleNode(String.Format("vmrun/commands/category/command[name=\"{0}\"]/parameters", command)).Attributes.GetNamedItem("guest_login_required").Value);
        }

        public ArrayList GetSuggestedOSs()
        {
            ArrayList operatingSystems = new ArrayList();

            foreach (XmlNode osNode in vmrunInfoXmlDoc.SelectNodes("vmrun/suggested_operating_systems/os"))
            {
                operatingSystems.Add(osNode.InnerText);
            }

            return operatingSystems;
        }
    }
}
